; ;******************* 宏定义 ************************

; 	LCDIO   EQU  P0	   ;LCD数据总线连接P0口
; 	RS      EQU  P1.0  ;Register select 连接P2.0
; 	RW      EQU  P1.1  ;Read/Write 连接P2.1
; 	E       EQU  P2.5  ;Enable 连接P2.2
; 	BF      EQU  P0.7  ;LCD的忙标志位
	
; 	CLOCKIO EQU  P2.7  ;DS1302数据IO
; 	SCLK    EQU  P1.7  ;DS1302时钟端口
; 	RST     EQU  P1.2  ;DS1302复位端口
	
; 	SECOND  EQU  60H   ;秒地址
; 	MINUTE  EQU  61H   ;分地址
; 	HOUR    EQU  62H   ;时地址
; 	YEAR    EQU  63H   ;日地址
; 	MOUTH   EQU  64H   ;月地址
; 	WEEK    EQU  65H   ;周地址
; 	DAY     EQU  66H   ;年地址
; ;***************************************************
	
; 	ORG 0000H
; 	AJMP MAIN
; 	ORG 0100H
; ;******************** 主函数 ************************

; MAIN: 
; 	LCALL CLOCK_INIT ;调用DS1602初始化函数
; 	LCALL LCD_INIT	 ;调用LCD1602初始化函数
; LOOP:
; 	LCALL GET_TIME	 ;调用获取时间函数，存储起始地址60H
; 	LCALL SHOW_TIME	 ;调用LCD显示时间函数
; 	MOV DPTR, #800   ;调用延时函数
; 	MOV A, #1
; 	LCALL T0_DELAY
	
; 	AJMP LOOP 
; ;***************************************************

; ;**************** LCD1602初始化 *********************
; LCD_INIT:
; 	MOV A, #01H  ;写入清屏命令 
; 	ACALL W_CMD
; 	MOV A, #38H  ;设置显示模式16*2显示
; 	ACALL W_CMD
; 	MOV A, #0CH  ;设置屏幕显示，无光标
; 	ACALL W_CMD
; 	MOV A, #14   ;设置右移
; 	ACALL W_CMD
; 	RET
; ;***************************************************
	  
; ;**************** LCD1602忙标志 *********************      
	  
; WAIT_BUSY: 
; 	MOV LCDIO,#0FFH
; 	CLR RS
; 	SETB RW
; 	CLR E
; 	NOP
; 	SETB E
; 	JB BF, WAIT_BUSY
; 	RET
; ;***************************************************

; ;*************** LCD1602写入命令函数 ****************

; W_CMD:
; 	LCALL WAIT_BUSY 
; 	MOV LCDIO, A ;把命令写到IO口处
; 	CLR RS	   ;清0，选择命令寄存器
; 	CLR RW
; 	SETB E	   ;模拟下降沿，命令写入LCD中
; 	NOP
; 	CLR E
; 	RET
; ;***************************************************

; ;*************** LCD1602写入数据函数 ****************

; W_DAT:
; 	LCALL WAIT_BUSY 
; 	MOV LCDIO, A
; 	SETB RS	   ;置1，选择数据寄存器
; 	CLR RW	   ;清0，为写入，置1，为读取
; 	SETB E	   ;模拟下降沿
; 	NOP 
; 	CLR E
; 	RET
; ;***************************************************

; ;************** DS1302写入字节函数 ******************
; ;将B写入DS1302  --传入参数B   --无传出参数

; INPUT: 
; 	MOV R4, #8
; INPUT_Rotate:
; 	MOV A, B
; 	RRC A
; 	MOV B, A
; 	MOV CLOCKIO, C
	
; 	SETB SCLK		 ;SCLK下降沿写入字节
; 	NOP
; 	CLR SCLK
	
; 	DJNZ R4, INPUT_Rotate
; 	RET
; ;***************************************************

; ;************** DS1302读出字节函数 ******************
; ;将DS1302数据读出到A

; OUTPUT:
; 	MOV R4, #8
; OUTPUT_Rotate:		
; 	MOV C, CLOCKIO
; 	RRC A
	
; 	SETB SCLK		 ;SCLK下降沿读出字节
; 	NOP
; 	CLR SCLK
	
; 	DJNZ R4, OUTPUT_Rotate
; 	RET 
; ;***************************************************

; ;************* 定义DS1302启示计时时间 ***************
; ;写入 20年 12月 19日 周6 13时 13分 13秒

; TIME_SET:	 
; 	 MOV SECOND,  #13H	  ;秒
; 	 MOV MINUTE,  #13H	  ;分
; 	 MOV HOUR,    #13H	  ;时
; 	 MOV DAY,     #19H	  ;日
; 	 MOV MOUTH,   #12H	  ;月
; 	 MOV WEEK,    #06H	  ;周
; 	 MOV YEAR,    #20H	  ;年
; 	 RET
; ;***************************************************

; ;****************** 初始化DS1302 ********************
; CLOCK_INIT:
; ;留32字节存储从DS1302读取的数据	
; 	MOV R0, #60H  ;从60H开始，依次增加
; 	MOV R1, #32H  ;作为索引，索引32个连续字节
; 	MOV A, #00H	  ;A起到中间变量，暂时存储00H
; CLR_BUF:
; 	MOV @R0, A	  ;间接寻址，把00H依次写入60H开始的32个字节中
; 	INC R0		  ;地址增1
; 	DJNZ R1, CLR_BUF   ;跳转，依次赋值
; ;写入命令字进行初始化	
; 	CLR RST		   ;模拟RST上升沿，启动数据传输（说明启动传输不是代表传输，还需要SCLK的上升沿
; 	CLR SCLK
; 	NOP									 ; 还需要SCLK的上升沿才能把数据按位依次传输过去）
; 	SETB RST
	
; 	MOV B, #8EH    ;命令字，写保护寄存器，此时不能对寄存器进行写操作了
; 	LCALL INPUT	 ;把命令字写如DS1302
	
; 	MOV B, #00H    ;WP清零，现在允许外部写入DS1302中数据
; 	LCALL INPUT	 ;把命令字写如DS1302
	
; 	LCALL TIME_SET	;设定初始化时间
	
; 	MOV R0, #SECOND	;把在RAM中地址为60H（存储数据为秒）数据给R0
; 	MOV R7, #7		;索引，秒、分......送七次
; 	MOV R1, #80H	;命令字。表示写入秒数据，当R2依次增二，表明开始进行写如分，时等数据.(这是规定，写如数据前先给命令字)

; WRITE:
; 	CLR RST		 ;模拟RST上升沿，启动数据传输
; 	CLR SCLK
; 	NOP  
; 	SETB RST
	
; 	MOV B, R1		;将命令字80H写入DS1302
; 	LCALL INPUT
; 	MOV A,@R0	    ;R0存储的秒地址，间接寻址将数据给A
; 	MOV B, A		;必须把数据传给B，因为写入函数（INPUT）传入参数是B
; 	LCALL INPUT
; 	INC R0		;R0增1表示由秒向分过渡，或者由分向时过渡，依次类推
; 	INC R1		;R1增2，表示由秒向分的命令字过渡，或者由分向时的命令字过渡，依次类推
; 	INC R1
	
; 	SETB SCLK
; 	CLR RST
; 	DJNZ R7, WRITE  ;循环7次，将秒，分，时，星期，天，月，年都写入
	
; 	MOV B, #8EH    ;写保护寄存器
; 	LCALL INPUT
	
; 	MOV B, #80H    ;WP置1，写保护
; 	LCALL INPUT		
	
; 	SETB SCLK
; 	CLR RST
; ;***************************************************

; ;***************** 获取时间函数 *********************

; GET_TIME:
; 	MOV R0, #SECOND		;把秒的地址给R0，以便依次读出数据
; 	MOV R7, #7		    ;用来循环
; 	MOV R1, #81H		;命令字。表示读出秒数据，当R2依次增二，表明开始进行写如分，时等数据.
; GET_TIME_Rotato:
; 	CLR RST				;模拟RST上升沿，表示启动数据传输
; 	CLR SCLK
; 	NOP
; 	SETB RST

; 	MOV B, R1		 	;把命令字给B，由B写如DS1302中
; 	LCALL INPUT			;写入命令字
; 	LCALL OUTPUT		;读出数据，读出的数据是保存到A中的
; 	MOV @R0, A			;现在将读出来的值放到秒或者分等的地址中
; 	INC R0				;地址加1，从而过渡到分，时等
; 	INC R1				;命令字需要加2才能进行读取
; 	INC R1
; 	SETB SCLK
; 	CLR RST
; 	DJNZ R7, GET_TIME_Rotato	;循环读取
; 	RET	   
; ;***************************************************

; ;***************** 显示时间函数 *********************

; SHOW_TIME:
; ;显示小时
; 	MOV A, #84H
; 	LCALL W_CMD
; 	MOV A, HOUR
; 	PUSH Acc
; 	SWAP A
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT  ;显示小时高位
	
; 	MOV A, #85H
; 	LCALL W_CMD
	
; 	POP Acc
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT ;显示小时低位

; ;显示符号-
; 	MOV A, #86H
; 	LCALL W_CMD
; 	MOV A, #2DH
; 	LCALL W_DAT

; ;显示分钟
; 	MOV A, #87H
; 	LCALL W_CMD
; 	MOV A, MINUTE
; 	PUSH Acc
; 	SWAP A
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT  ;显示分钟高位
	
; 	MOV A, #88H
; 	LCALL W_CMD
	
; 	POP Acc
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT ;显示分钟低位

; ;显示符号-
; 	MOV A, #89H
; 	LCALL W_CMD
; 	MOV A, #2DH
; 	LCALL W_DAT

; ;显示秒
; 	MOV A, #8AH
; 	LCALL W_CMD
; 	MOV A, SECOND
; 	PUSH Acc
; 	SWAP A
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT  ;显示秒高位
	
; 	MOV A, #8BH
; 	LCALL W_CMD
	
; 	POP Acc
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT ;显示秒低位

; ;显示年
; 	MOV A, #0C3H
; 	LCALL W_CMD
; 	MOV A, YEAR
; 	PUSH Acc
; 	SWAP A
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT  ;显示年高位
	
; 	MOV A, #0C4H
; 	LCALL W_CMD
	
; 	POP Acc
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT ;显示年低位

; ;显示符号-
; 	MOV A, #0C5H
; 	LCALL W_CMD
; 	MOV A, #2DH
; 	LCALL W_DAT

; ;显示月
; 	MOV A, #0C6H
; 	LCALL W_CMD
; 	MOV A, MOUTH
; 	PUSH Acc
; 	SWAP A
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT  ;显示月高位
	
; 	MOV A, #0C7H
; 	LCALL W_CMD
	
; 	POP Acc
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT ;显示月低位

; ;显示符号-
; 	MOV A, #0C8H
; 	LCALL W_CMD
; 	MOV A, #2DH
; 	LCALL W_DAT

; ;显示日
; 	MOV A, #0C9H
; 	LCALL W_CMD
; 	MOV A, DAY
; 	PUSH Acc
; 	SWAP A
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT  ;显示日高位
	
; 	MOV A, #0CAH
; 	LCALL W_CMD
	
; 	POP Acc
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT ;显示日低位

; ;显示符号-
; 	MOV A, #0CBH
; 	LCALL W_CMD
; 	MOV A, #2DH
; 	LCALL W_DAT

; ;显示周
; 	MOV A, #0CCH
; 	LCALL W_CMD
; 	MOV A, WEEK
	
; 	ANL A, #0FH
; 	ORL A, #30H
; 	LCALL W_DAT ;显示周
	
; 	RET
; ;****************** T0延时函数 *******************

; T0_DELAY:
; 	PUSH Acc
; 	LCALL T0_WAIT
; 	POP Acc
; 	DEC A
; 	JNZ T0_DELAY
; 	RET
; T0_WAIT:
; 	XRL DPL, #0FFH
; 	XRL DPH, #0FFH
; 	INC DPTR
; T0_1:
; 	MOV TL0, #09CH
; 	MOV TH0, #0FFH
; 	MOV TMOD, #1
; 	SETB TCON.4
; T0_2:
; 	JNB TCON.5, T0_2
; 	CLR TCON.4
; 	CLR TCON.5
; 	INC DPTR
; 	MOV A, DPL
; 	MOV A, DPH
; 	JNZ T0_1
; 	RET
; ;***************************************************
; 	END



; ;/* define constants */
; T1MS        EQU 0FC66H                  ;1ms timer calculation method in 12T mode is (65536-18432000/12/1000)

; ;/* define SFR */
; TEST_LED    BIT  P1.0                   ;work LED, flash once per second

; ;/* define variables */
; COUNT DATA 20H                          ;1000 times counter (2 bytes)

; ;-----------------------------------------------

;     ORG     0000H
;     LJMP    MAIN
;     ORG     001BH
;     LJMP    TM1_ISR

; ;-----------------------------------------------

; ;/* main program */
; MAIN:
;     MOV     TMOD,#10H                   ;set timer1 as mode1 (16-bit)
;     MOV     TL1,#LOW T1MS               ;initial timer1 low byte
;     MOV     TH1,#HIGH T1MS              ;initial timer1 high byte
;     SETB    TR1                         ;timer1 start running
;     SETB    ET1                         ;enable timer1 interrupt
;     SETB    EA                          ;open global interrupt switch
;     CLR     A
;     MOV     COUNT,A
;     MOV     COUNT+1,A                   ;initial counter
;     SJMP    $

; ;-----------------------------------------------

; ;/* Timer1 interrupt routine */
; TM1_ISR:
;     PUSH    ACC
;     PUSH    PSW
;     MOV     TL1,#LOW T1MS               ;reload timer1 low byte
;     MOV     TH1,#HIGH T1MS              ;reload timer1 high byte
;     MOV     A,COUNT
;     ORL     A,COUNT+1                   ;check whether count(2byte) is equal to 0
;     JNZ     SKIP
;     MOV     COUNT,#LOW 1000             ;1ms * 1000 -> 1s
;     MOV     COUNT+1,#HIGH 1000
;     CPL     TEST_LED                    ;work LED flash
; SKIP:
;     CLR     C
;     MOV     A,COUNT                     ;count--
;     SUBB    A,#1
;     MOV     COUNT,A
;     MOV     A,COUNT+1
;     SUBB    A,#0
;     MOV     COUNT+1,A
;     POP     PSW
;     POP     ACC
;     RETI

; DSEG AT 30H

;     ; define timer data start
;     timer_count_1: DS 2
;     ; define timer data end
; ;-----------------------------------------------

;     END





; ; ; 8051 汇编独立按键程序

; ; ORG 0000H
; ;     ; 中断向量表
; ;     LJMP MAIN

; ; ORG 0030H
; ; MAIN:
; ;     MOV P1, #0FFH   ; 设置 P1 端口为输入（高电平）
; ;     MOV P2, #00H    ; 清除 P2 端口显示

; ; SCAN:
; ;     MOV A, P1       ; 读取 P1 端口
; ;     ANL A, #0F0H    ; 保留低 4 位 (P1.0-P1.3)
; ;     CJNE A, #0F0H, CHECK_KEY ; 如果低 4 位有任何变化，检测按键
; ;     SJMP SCAN       ; 否则继续扫描

; ; CHECK_KEY:
; ;     MOV A, P1
; ;     ANL A, #0F0H    ; 保留低 4 位 (P1.0-P1.3)
; ;     CJNE A, #0FEH, KEY1_PRESSED ; 如果 P1.0 低电平
; ;     CJNE A, #0FDH, KEY2_PRESSED ; 如果 P1.1 低电平
; ;     CJNE A, #0FBH, KEY3_PRESSED ; 如果 P1.2 低电平
; ;     CJNE A, #0F7H, KEY4_PRESSED ; 如果 P1.3 低电平
; ;     SJMP SCAN       ; 没有按键按下，继续扫描

; ; KEY1_PRESSED:
; ;     MOV P2, #01H    ; 显示按键 1 被按下
; ;     CALL DELAY      ; 延时消抖
; ;     SJMP SCAN

; ; KEY2_PRESSED:
; ;     MOV P2, #02H    ; 显示按键 2 被按下
; ;     CALL DELAY      ; 延时消抖
; ;     SJMP SCAN

; ; KEY3_PRESSED:
; ;     MOV P2, #03H    ; 显示按键 3 被按下
; ;     CALL DELAY      ; 延时消抖
; ;     SJMP SCAN

; ; KEY4_PRESSED:
; ;     MOV P2, #04H    ; 显示按键 4 被按下
; ;     CALL DELAY      ; 延时消抖
; ;     SJMP SCAN

; ; DELAY:
; ;     MOV R7, #255    ; 简单延时循环
; ; D1: MOV R6, #255
; ; D2: DJNZ R6, D2
; ;     DJNZ R7, D1
; ;     RET

; ; END